import UIKit


//可选链：是一种请求和调用属性，方法及下标脚本的过程。它的可选性体现在请求或调佣的目标当前可能是nil


//可选链可替代强制解析.---》在调用的属性，方法，或脚本的可选值后面放一个问号，可以定义一个可选链。

class Person1 {
    var presidence: Residence1?
}

class Residence {
    var numberOfRooms = 1
}

let john = Person1()
//let roomCont = john.presidence!.numberOfRooms
if let roomCount = john.presidence?.numberOfRooms {
    print("john's president has \(roomCount) rooms")
} else {
    print("unable to retrieve the number of rooms.")
}

john.presidence = Residence1()

john.presidence?.numberOfRooms // 1


//为可选链定义模型类
class Residence1 {
    var rooms: [Room] = []
    var numberOfRooms: Int { return rooms.count }
    
    subscript(i: Int) -> Room {
        return rooms[i]
}
    func printNumberRooms() {
        print("the number of rooms is \(numberOfRooms)")
    }
    var address: Address?
}
class Room {
    let name: String
    init(name: String) {
        self.name = name
    }
}

class Address {
    var buildingName: String?
    var buildingNumber: String?
    var street: String?
    
    func buildingIdentifier() -> String? {
        if (buildingName != nil) {
            return buildingName
        } else if (buildingNumber != nil) {
            return buildingNumber
        } else {
            return nil
        }
}
}
//通过可选链调用属性
let sum = Person1()
if let roomCount = sum.presidence?.numberOfRooms {
    print("sum 's residence hass \(roomCount) rooms.")
} else {
    print("unable to retrive the number of room.")
}

//使用可选链定义下标脚本
if let firstRoomName = sum.presidence?.rooms[0].name {
    print("111")
} else {
    print("222")
}

    
//连接多层
let johnAddress = Address()
johnAddress.buildingName = "the larches"
johnAddress.street = "Laure street"
john.presidence?.address = johnAddress

if let johnStreet = sum.presidence?.address?.street {
    print("john'stree name is \(johnStreet)")
} else {
    print("unbable to retrieve the address")
}

if let buidingIdentifier = john.presidence?.address?.buildingIdentifier()?.uppercased() {
    print("john' s building identifer is \(buidingIdentifier)")
}
    
//上面最后一个？放在()后面是因为你想要链接的可选值是buildingIdentifier方法的返回值。不是buildingIdentifier方法本身。

